package com.example.blogapi.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blogapi.domain.*;
import com.example.blogapi.domain.dos.Archives;
import com.example.blogapi.mapper.ArchivesMapper;
import com.example.blogapi.mapper.MsArticleBodyMapper;
import com.example.blogapi.mapper.MsArticleMapper;
import com.example.blogapi.mapper.MsArticleTagMapper;
import com.example.blogapi.service.*;
import com.example.blogapi.utils.ReplaceUtils;
import com.example.blogapi.utils.UserThreadLocal;
import com.example.blogapi.vo.ArticleBodyVo;
import com.example.blogapi.vo.ArticleVo;
import com.example.blogapi.vo.Result;
import com.example.blogapi.vo.TagVo;
import com.example.blogapi.vo.param.ArticleParam;
import com.example.blogapi.vo.param.PageParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
* @author 13723
* @description 针对表【ms_article】的数据库操作Service实现
* @createDate 2022-10-20 15:21:07
*/
@Service
public class MsArticleServiceImpl extends ServiceImpl<MsArticleMapper, MsArticle>
implements MsArticleService {
    @Autowired
    MsArticleMapper msArticleMapper;
    @Autowired
    ArchivesMapper archivesMapper;
    @Autowired
    MsTagService msTagService;
    @Autowired
    MsSysUserService msSysUserService;
    @Autowired
    MsArticleBodyMapper msArticleBodyMapper;
    @Autowired
    CategoryService categoryService;
    @Autowired
    ThreadService threadService;
    @Autowired
    MsArticleTagMapper articleTagMapper;

    @Override
    public List<ArticleVo> listArticlesPage(PageParam pageParam) {
        QueryWrapper<MsArticle> queryWrapper = new QueryWrapper<>();
        Page<MsArticle> articlePage = new Page<>(pageParam.getPage(),pageParam.getPageSize());
        queryWrapper.orderByDesc("weight","create_date");
        Page<MsArticle> page = this.page(articlePage, queryWrapper);
        List<MsArticle> records = page.getRecords();
        List<ArticleVo> articleVos = copyToAoList(records,true,true,false,false);
        return articleVos;
    }


    private List<ArticleVo> copyToAoList(List<MsArticle> originList, boolean isTag, boolean isAuthor, boolean isBody, boolean isCategory) {

        List<ArticleVo> AoList = new ArrayList<>();
        for (MsArticle msArticle :originList) {
            ArticleVo articleVo = copy(msArticle,isTag,isAuthor,isBody,isCategory);
            AoList.add(articleVo);
        }
        return AoList;
    }

    public ArticleVo copy(MsArticle originArticle, boolean isTag, boolean isAuthor, boolean isBody, boolean isCategory){
        ArticleVo articleVo = new ArticleVo();
        BeanUtils.copyProperties(originArticle,articleVo);
        if (isTag){
            List<MsTag> tags = msTagService.getTagsByArticleId(articleVo.getId());
            articleVo.setTags(tags);
        }
        if(isAuthor){
            MsSysUser user = msSysUserService.getById(articleVo.getAuthorId());
            if (user!=null)
                articleVo.setAuthorName(user.getNickname());
        }
        if (isBody){
            Long bodyId = originArticle.getBodyId();
            articleVo.setArticleBodyVo(findArticleBodyById(bodyId));
        }
        if (isCategory){
            Long categoryId = originArticle.getCategoryId();
            articleVo.setCategoryVo(categoryService.findCategoryById(categoryId));
        }
        return articleVo;
    }

    private ArticleBodyVo findArticleBodyById(Long bodyId) {
        MsArticleBody articleBody = msArticleBodyMapper.selectById(bodyId);
        ArticleBodyVo articleBodyVo = new ArticleBodyVo();
        BeanUtils.copyProperties(articleBody,articleBodyVo);
        return articleBodyVo;
    }

    @Override
    public List<ArticleVo> getHotArticles(int limit) {
        QueryWrapper<MsArticle> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("view_counts");
        queryWrapper.select("id","title");
        queryWrapper.last("limit "+limit);
        List<MsArticle> msArticles = msArticleMapper.selectList(queryWrapper);
        List<ArticleVo> articleVos = copyToAoList(msArticles,true,true,false,false);
        return articleVos;
    }

    @Override
    public List<ArticleVo> getNewArticles(int limit) {
        QueryWrapper<MsArticle> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_date");
        queryWrapper.select("id","title");
        queryWrapper.last("limit "+limit);
        List<MsArticle> msArticles = msArticleMapper.selectList(queryWrapper);
        List<ArticleVo> articleVos = copyToAoList(msArticles,true,true,false,false);
        return articleVos;
    }

    @Override
    public List<Archives> listArchives() {
        List<Archives> archives = archivesMapper.listArchives();
        return archives;
    }

    @Override
    public ArticleVo findArticleById(Long id) {
        MsArticle article = msArticleMapper.selectById(id);
        ArticleVo articleVo = copy(article,true,true,true,true);
//        System.out.println("====================================");
//        System.out.println("文章长度为"+articleVo.getArticleBodyVo().getContent().length());
//        String content = ReplaceUtils.replaceAngleBrackets(articleVo.getArticleBodyVo().getContent());
//        articleVo.getArticleBodyVo().setContent(content);
//        System.out.println("====================================");

//        开启线程池加载更新观看次数，防止影响查看线程的进行
        threadService.updateArticleViewCount(article);
        return articleVo;
    }

    /**
     * 发布文章逻辑
     * @param articleParam
     * @return
     */
    @Override
    @Transactional
    public Result publish(ArticleParam articleParam) {
        MsSysUser user = UserThreadLocal.get();
        MsArticle article = new MsArticle();
        article.setAuthorId(user.getId());
        article.setCategoryId(articleParam.getCategory().getId());
        article.setCreateDate(System.currentTimeMillis());
        article.setCommentCounts(0);
        article.setSummary(articleParam.getSummary());
        article.setTitle(articleParam.getTitle());
        article.setViewCounts(0);
        article.setWeight(MsArticle.Article_Common);
        article.setBodyId(-1L);
//        插入文章
        msArticleMapper.insert(article);
        //tags
        List<TagVo> tags = articleParam.getTags();
        if (tags != null) {
            for (TagVo tag : tags) {
                MsArticleTag articleTag = new MsArticleTag();
                articleTag.setArticleId(article.getId());
                articleTag.setTagId(tag.getId());
                this.articleTagMapper.insert(articleTag);
            }
        }
        MsArticleBody articleBody = new MsArticleBody();
        articleBody.setContent(articleParam.getBody().getContent());
        articleBody.setContentHtml(articleParam.getBody().getContentHtml());
        articleBody.setArticleId(article.getId());
        msArticleBodyMapper.insert(articleBody);

        article.setBodyId(articleBody.getId());
        msArticleMapper.updateById(article);
        HashMap<String,String> hashMap = new HashMap();
        hashMap.put("id",article.getId().toString());
        return Result.success(hashMap);
    }
}
